﻿/*
 * Copyright (C) 2011, EADS France
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * Author: Laurent WOUTERS
 */

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Hime.Redist.Parsers;

namespace xowl.gmi.compiler.ast
{
    class MinimalAST
    {
        protected static Random rand = new Random();

        protected string symbol;
        protected string route;
        protected List<MinimalAST> children;
        protected List<Parameter> parameters;

        public void AddParameters(List<Parameter> parameters) { this.parameters.AddRange(parameters); }

        public MinimalAST(string symbol)
        {
            this.symbol = symbol;
            this.children = new List<MinimalAST>();
            this.parameters = new List<Parameter>();
        }
        public MinimalAST(string symbol, string route)
        {
            this.symbol = symbol;
            this.route = route;
            this.children = new List<MinimalAST>();
            this.parameters = new List<Parameter>();
        }
        public MinimalAST(SyntaxTreeNode ast)
        {
            this.symbol = ((SymbolTokenText)ast.Children[0].Symbol).ValueText;
            this.parameters = new List<Parameter>();
            foreach (SyntaxTreeNode child in ast.Children[1].Children)
                parameters.Add(new Parameter(child));
            if (ast.Children[2].Children.Count != 0)
                this.route = ((SymbolTokenText)ast.Children[2].Children[0].Symbol).ValueText;
            this.children = new List<MinimalAST>();
            foreach (SyntaxTreeNode child in ast.Children[3].Children)
            {
                string name = ((SymbolTokenText)child.Children[0].Symbol).ValueText;
                if (name == "Boolean" || name == "Integer" || name == "Float" || name == "String")
                    this.children.Add(new MinimalASTPlaceholder(child));
                else
                    this.children.Add(new MinimalAST(child));
            }
        }

        public void AddChild(MinimalAST child)
        {
            children.Add(child);
        }

        public void Write(StreamWriter writer)
        {
            writer.Write(symbol);
            if (parameters.Count != 0)
            {
                writer.Write("<");
                bool first = true;
                foreach (Parameter param in parameters)
                {
                    if (!first) writer.Write(", ");
                    param.Write(writer);
                    first = false;
                }
                writer.Write(">");
            }
            if (route != null)
            {
                writer.Write("@");
                writer.Write(route);
            }
            WriteChildren(writer);
        }

        protected void WriteChildren(StreamWriter writer)
        {
            if (children.Count == 0)
                return;
            writer.Write("(");
            bool first = true;
            foreach (MinimalAST child in children)
            {
                if (!first) writer.Write(" ");
                first = false;
                child.Write(writer);
            }
            writer.Write(")");
        }

        public void WriteOWL(StreamWriter writer, string id)
        {
            writer.WriteLine("ClassAssertion(ast:ASTNode " + id + ")");
            writer.WriteLine("\t\t\tObjectPropertyAssertion(ast:symbol " + id + " view:" + symbol + ")");
            if (route != null)
                writer.WriteLine("\t\t\tMeta(ObjectPropertyAssertion(view:" + route + " " + id + " " + id + "))");
            WriteOWLChildren(writer, id, id);
        }

        protected virtual string WriteOWLInner(StreamWriter writer, string root, out string decorator)
        {
            string id = WriteOWLHead(writer, out decorator);
            writer.WriteLine("\t\t\tObjectPropertyAssertion(ast:symbol " + id + " view:" + symbol + ")");
            if (route != null)
                writer.WriteLine("\t\t\tMeta(ObjectPropertyAssertion(view:" + route + " " + root + " " + id + "))");
            WriteOWLChildren(writer, id, root);
            return id;
        }

        protected string WriteOWLHead(StreamWriter writer, out string decorator)
        {
            string id = "?" + rand.Next().ToString("X");
            decorator = "?" + rand.Next().ToString("X");
            writer.WriteLine("\t\t\tClassAssertion(ast:ASTNode " + id + ")");
            writer.WriteLine("\t\t\tMeta(ClassAssertion(ast:Decorator " + decorator + "))");
            writer.WriteLine("\t\t\tMeta(ObjectPropertyAssertion(ast:decorators " + id + " " + decorator + "))");
            foreach (Parameter param in parameters)
                param.WriteOWL(writer, decorator);
            return id;
        }

        protected void WriteOWLChildren(StreamWriter writer, string parent, string root)
        {
            int index = 0;
            foreach (MinimalAST child in children)
            {
                string decorator = null;
                string id = child.WriteOWLInner(writer, root, out decorator);
                writer.WriteLine("\t\t\tObjectPropertyAssertion(ast:children " + parent + " " + id + ")");
                writer.WriteLine("\t\t\tMeta(ObjectPropertyAssertion(ast:parent " + decorator + " " + parent + "))");
                writer.WriteLine("\t\t\tMeta(DataPropertyAssertion(ast:index " + decorator + " " + index + "))");
                index++;
            }
        }
    }
}
